package com.bwie.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bwie.mappe.UserMapper;
import com.bwie.pojo.TbUser;
import com.bwie.service.UserService;
import com.bwie.utils.MobileMessageUtil;
import com.bwie.utils.R;
import com.bwie.vo.LoginVo;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.digest.Md5Crypt;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Title:
 * @BelongProjecet month0617
 * @BelongPackage com.bwie.service.impl
 * @Description:
 * @Copyright 研发一部
 * @Author: Mr.yan
 * @Date: 2024/6/17 9:35
 * @Version V1.0
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public R sendCode(String mobile) {
        //1.判断验证阿是否过期，未过期不能重复发送
        String codeKey = "code:mobile:"+mobile;
        Boolean hasKey = stringRedisTemplate.hasKey(codeKey);
        if (hasKey){
            return R.error(500,"验证码未过期不能重复发送");
        }
        //2.判断手机号格式是否正确
        boolean b = Validator.isMobile(mobile);
        if (!b){
            return R.error(500,"手机号格式输入错误");
        }
        //3.生成验证码
        String code = RandomUtil.randomNumbers(4);
        //4.获取验证码
        Boolean aBoolean = MobileMessageUtil.sendMobileMessage(mobile, code);
        if (!aBoolean){
            return R.error(500,"验证码发送失败");
        }
        //5.存入缓存中。设置有效期
        stringRedisTemplate.opsForValue().set(codeKey,code,1, TimeUnit.MINUTES);

        return R.success(code);
    }

    @Override
    public R userLogin(LoginVo loginVo) {
        //1.判断该手机号是否注册
        TbUser tbUser = userMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getMobile, loginVo.getMobile())
        );
        if (tbUser == null){
            return R.error(404,"该手机号未注册，请重新输入");
        }
        //2.判断是密码登录还是验证码登录
        if (loginVo.getLoginNum() == 1){
            //如果是1的话就是密码登录
            //密码加密
            String bcrypt = DigestUtil.bcrypt(tbUser.getPassword());
            System.out.println(bcrypt);
            //校验密码是否正确
            boolean b = DigestUtil.bcryptCheck(loginVo.getPassword(), tbUser.getPassword());
            if (!b){
                return R.error(500,"密码输入错误，如若忘记，可以忘记密码重置密码");
            }
        }else {
            //使用验证码登录
            //判断验证码是否正确
            String codeKey = "code:mobile:"+loginVo.getMobile();
            String codeRedis = stringRedisTemplate.opsForValue().get(codeKey);
            if (!codeRedis.equals(loginVo.getCode())){
                return R.error(500,"验证码输入错误，请重新输入");
            }

        }

        //3.生成token，并设置有效期
        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256, "bwie")
                .setIssuedAt(new Date())
                .claim("id", tbUser.getId())
                .claim("role", tbUser.getUserRole())
                .compact();

        //4.存入缓存中并设置有效期
        String tokenKey = "token:id"+tbUser.getId();
        stringRedisTemplate.opsForValue().set(tokenKey,token,30,TimeUnit.MINUTES);

        tbUser.setToken(token);
        return R.success(tbUser);
    }

    @Override
    public R forgetPassword(LoginVo loginVo) {
        //1.判断手机号格式是否正确
        boolean b = Validator.isMobile(loginVo.getMobile());
        if (!b){
            return R.error(500,"手机号格式输入错误");
        }

        //2.判断两次输入的密码是否正确
        if (!loginVo.getPassword().equals(loginVo.getPasswordTwo())){
            return R.error(500,"两次密码输入的不一致，请检查");
        }
        //3.判断验证码是否正确
        String codeKey = "code:mobile:"+loginVo.getMobile();
        String codeRedis = stringRedisTemplate.opsForValue().get(codeKey);
        if (!codeRedis.equals(loginVo.getCode())){
            return R.error(500,"验证码输入错误，请重新输入");
        }
        //4.修改密码
        String bcrypt = DigestUtil.bcrypt(loginVo.getPassword());
        TbUser tbUser = userMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getMobile, loginVo.getMobile())
        );
        tbUser.setPassword(bcrypt);
        userMapper.updateById(tbUser);
        return R.success();
    }
}
